package org.skycloud.mybatis.dialect.impl;

import org.apache.ibatis.session.RowBounds;
import org.skycloud.mybatis.dialect.Dialect;
import org.skycloud.mybatis.utils.StringBuilderUtils;

public final class OracleDialect implements Dialect {

	private static final String FOR_UPDATE = " for update";
	private static final String HAS_OFFSET_SELECT = "select * from ( select row_.*, rownum rownum_ from ( ";
	private static final String HAS_OFFSET_WHERE_A = " ) row_ where rownum <= ";
	private static final String HAS_OFFSET_WHERE_B = ") where rownum_ > ";
	private static final String NO_OFFSET_SELECT = "select * from ( ";
	private static final String NO_OFFSET_WHERE = " ) where rownum <= ";

	@Override
	public String getSql(String sql, RowBounds rowBounds) {
		sql = sql.trim();

		boolean isForUpdate = false;
		if (sql.toLowerCase().endsWith(FOR_UPDATE)) {
			sql = sql.substring(0, sql.length() - 11);
			isForUpdate = true;
		}

		StringBuilder buf = StringBuilderUtils.getThreadLocalStringBuilder(0);
		boolean hasOffset = rowBounds.getOffset() > 0;
		if (hasOffset) {
			buf.append(HAS_OFFSET_SELECT);
		} else {
			buf.append(NO_OFFSET_SELECT);
		}

		buf.append(sql);

		if (hasOffset) {
			buf.append(HAS_OFFSET_WHERE_A).append(rowBounds.getOffset() + rowBounds.getLimit())
					.append(HAS_OFFSET_WHERE_B).append(rowBounds.getOffset());
		} else {
			buf.append(NO_OFFSET_WHERE).append(rowBounds.getLimit());
		}

		if (isForUpdate) {
			buf.append(FOR_UPDATE);
		}

		return buf.toString();
	}

}
